/**
 * 版权所有（c）2021. 上海海鼎信息工程股份有限公司，保留所有权利
 */
package com.lovely602.design.creation.factorymethod;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.InputStream;

/**
 * 工厂方法模式是一种创建型设计模式，其主要目的是定义一个用于创建对象的接口，但让子类决定实例化哪个类。
 * <p>
 * 这种模式通过将实例化任务委托给子类来处理对象的创建，而不是在父类中直接创建对象。
 * <p>
 * 这样做的好处是可以将对象的创建与使用代码解耦，从而使代码更加灵活、可扩展和可维护
 *
 * @author lizhixing
 */
public class FactoryMethodTest {

  public static void main(String[] args) {
    try {
      Product a;
      FactoryMethod af;
      af = (FactoryMethod) getObject();
      a = af.create();
      a.show();
    } catch (Exception e) {
      System.out.println(e.getMessage());
    }
  }

  /**
   * 该方法用于从XML配置文件中提取具体类类名，并返回一个实例对象
   */
  public static Object getObject() {
    try {
      //创建文档对象
      DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
      DocumentBuilder builder = dFactory.newDocumentBuilder();
      Document doc;
      InputStream is = ClassLoader.getSystemResourceAsStream("xml/factorymethod-config.xml");
      doc = builder.parse(is);
      //获取包含类名的文本节点
      NodeList nl = doc.getElementsByTagName("className");
      Node classNode = nl.item(0).getFirstChild();
      String cName = classNode.getNodeValue();
      //通过类名生成实例对象并将其返回
      Class<?> c = Class.forName(cName);
      return c.newInstance();
    } catch (Exception e) {
      e.printStackTrace();
      return null;
    }
  }
}
